// 一、函数的概念：函数可以用过名称进行引用，并且自包含微信程序的代码块。
// 二、函数的特点
//    1.函数名是引用函数的关键
//    2.函数是可以重复使用的代码块，从而降低代码的重复率
//    3.函数内部是一个完整的代码体系，可以完成指定的功能

// 三、声明函数
// 1.字面量声明函数
// 基础语法：
// function 函数名（形式参数）{
//     函数体：具体实现函数功能的代码
// }
// 举例：输入两个数字，求乘积
// function test(x,y){

//     let s=x*y;
//     x=x+10;
//     y=y+10;
//     // console.log("xxxx:",s);
//     return [s,x];
//     console.log(111);
// }
// 调用函数：函数名(实际参数)
// let x=8,y=9;
// let sum=test(x,y);//用一个变量来接收函数调用的返回值
// console.log(sum);//72 

// console.log(x,y);
// 函数的三要素：
// （一）函数功能：输入两个数字，求乘积
// （二）函数参数
//   1.形式参数（形参）：写在声明函数时，函数名后面的小括号里面；形参数量没有限制；形参变量不需要声明;
//     形参是用于接受实参传过来的值(按照位置一一传值)，然后用于函数体内部的计算;形参变量只能用于函数体内部;
//     行参变量名可以和实参相同
//     
//   2.实际参数（实参）:写在调用函数时，函数名后面的小括号里面；实参数量没有限制;实参如果是变量就必须要声明
//     实参是把具体的值按照位置顺序依次传给形参;实参变量根据具体作用域进行使用，不仅仅局限于函数体内部使用

// (三)函数返回值:函数的返回值是由return关键字返回，如果没有return，就是返回默认值undefined
// 1.return每次只能返回一个值,如果需要返回多个值，就把数据放在数组中一起返回
// 2.return后面的代码不会执行
// 3.函数中执行代码到return，表示函数结束，强制结束函数


// 2.函数表达式声明函数
// 基础语法：
// let 变量名=function (形参){
//     函数体：函数具体功能代码
// }


// 输入一个字符串，保留字符串中的字母
// let test=function(str){
//     let newStr="";
//     for(let i=0;i<str.length;i++){
//         if(str[i]>="A" && str[i]<="Z" || str[i]>="a" && str[i]<="z"){
//             newStr+=str[i];
//         }
//     }
//     return newStr;
// }

// 第一种输出返回值的方法：
// let s=test("hsgadiue6328463");
// console.log(s);
// 第二种输出返回值的方法：
// console.log(test("dhfgajs4536sdf"));

// let z=test("safdh324sa")+123;
// console.log(z);



// （一）函数功能：保留字符串中的字母
// （二）参数
// 1.形参：str
// 2.实参："hsgadiue6328463"
// （三）返回值



// function test(a){
//     // 函数在执行前会自动创建一个叫arguments的伪数组对象
//     console.log(arguments);
//     console.log(arguments[5]);
//     console.log(a);
// }
// test(1,2,3,4,5,6,7,8);


// // 伪数组对象:本质依然是对象，只是访问方式像数组
// let obj={
//     name:"小米",
//     2:"哈哈哈"
// }
// console.log(obj.name);
// console.log(obj[2]);


// 3.箭头函数
// 基本语法：
// let 变量=(形参)=>{
//     函数体
// }

// let test=a=>a*a;


// console.log(test(3)) ;


// 四、提升
// （一）变量提升：只用使用var声明的变量会把变量声明的部分提升到当前作用域的最顶端
// console.log(a);//undefined
// var a=10;

// (二)函数提升：只用使用字面量方法声明的函数有函数提升，会把函数声明提升到当前作用域最顶端
// console.log(move(33));//undefined
// function move(x){
//     console.log(x);//33
// }
// var move2;
// console.log(move2(44));
// var move2=function(x){
//     console.log(x);
// }


// 五、作用域
// 1.全局作用域：全局变量
// 2.局部作用域：局部变量
// 3.函数作用域：函数内部就是函数作用域；函数作用域也是一种局部作用域，只是比局部作用域更加严格

// 特殊：var声明的变量在函数作用域中是局部变量，只能用于函数内部；除此之外，var声明的变量都是全局变量
//      遗漏声明的变量永远是全局变量

// function test(){
//     y=66;//全局变量
//     var a=10;//局部变量，只能用于函数内容
//     console.log("函数内部！");   
// }
// test()
// console.log(y);

// var t = 10;//全局变量

// function test(test) {
//     t = t + test;//t=10+10
//     console.log(t);//
//     t = 3;//
//     console.log(t);//3
// }
// test(t);

// function add() {
//     var sum = 1 + 2;
//     console.log(sum);
// }
// console.log(sum);

// var num = 5;

// function fn(num) {
//     num = 1;
// }
// fn(num);
// console.log(num);


// var a = b = 10;
// 相当于
// var a=10;
// b=10;
// 立即执行函数
// (函数声明)()

// (function () {
//     // var a = b = 20
//     // 相当于
//     var a=20;//局部变量
//     b=20;//遗漏声明，全局变量

// })();
// console.log(b);

// 六、回调函数：把函数A作为实参传给函数B，那么函数A就是回调函数
// function fn(){
//     console.log("123");
// }

// function test(f,x){
//     f();//调用函数
//     console.log(x);
//     console.log(456);
// }
// test(fn,66);

// let arr=[23,1,4,7,5,9];
// let fn=function(a,b){
//     return a-b;
// }
// arr.sort(fn);
// console.log(arr);

// 七、常见的回调函数
// 1.arr.sort():数组排序
// 2.arr.every():判断数组中的内容是否都符合条件，都符合条件返回true，有一个不符合就返回false
// let arr=[1,2,3,4,5];
// let i=arr.every(function(item){
//     if(item%2==0){
//         return 1;
//     }else{
//         return 0;
//     }

// })
// console.log(i);//false

// 3.arr.some():判断数组中的内容是否都符合条件，有一个符合条件返回true，全部都不符合就返回false

// 4.arr.filter():过滤数组中结果为true的数据，返回值是数组
// let arr=[1,2,3,4,5];
// let i=arr.filter(function(item){
//     // item:表示数组中的每一项，不需要再遍历数组
//     if(item%2==0){
//         return 1;
//     }else{
//         return 0;
//     }

// })
// console.log(i);

// 5. arr.forEach():遍历数组，没有返回值

// 6.arr.map():运行回调函数，返回一个数组，数组中是运行回调函数的结果
// let arr=[1,2,3,4,5];
// let i=arr.map(function(item){
//     if(item%2==0){
//         return 1;
//     }else{
//         return 55;
//     }
// })
// console.log(i);//[ 55, 1, 55, 1, 55 ]

// 7.arr.reduce():数组中数据的累计结果
// let arr=[1,2,3,4,5];
// let i=arr.reduce(function(pre,cur,index){
//     // pre:前面数据的累计结果
//     // cur：下一个数据
//     console.log(pre,cur);
//     return pre/cur;

// })
// console.log(i);

// 八、链式调用：清楚每一次调用方法（函数）之后的返回值是什么数据类型，根据不同的数据类型，采用不同的方法，才可以进行后续的调用
// let arr=[4,5,6,10,11,12,1,2,3,7,8,9];
// let i=arr.filter(function(item){
//     // item:表示数组中的每一项，不需要再遍历数组
//     if(item%2==0){
//         return 1;
//     }else{
//         return 0;
//     }

// })
// let z=i.sort(function(a,b){
//     return a-b;
// }).push(88).toFixed(2);

// console.log(z);


// 总结：
// 1.函数的概念和特点
// 2.创建函数的3种方法
// 3.函数的三要素
// 4.函数作用域和函数提升
// 5.回调函数